package com.eqxiu.ieditor.api.controller.order;


import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;

import com.eqxiu.ieditor.api.mall.IMallServiceApi;
import com.eqxiu.ieditor.api.order.IOrderItemServiceApi;
import com.eqxiu.ieditor.api.order.IOrderServiceApi;
import com.eqxiu.ieditor.dto.*;
import com.eqxiu.user.api.UserApi;
import com.eqxiu.user.api.dto.User;
import com.eqxiu.user.api.dto.UserExt;
import com.eqxiu.user.api.dto.UserMemberDTO;
import com.google.common.collect.Maps;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.eqxiu.ieditor.api.controller.BaseApiController;
import com.eqxiu.ieditor.api.controller.order.doc.OrderApiDoc;
import com.eqxiu.ieditor.commons.web.MsgCode;
import com.eqxiu.ieditor.commons.web.ResultData;
import com.eqxiu.ieditor.interceptor.UserContext;


import eqxiu.mall.product.service.api.AsyncOrderCallbackServiceApi;
import eqxiu.mall.product.service.api.ProductServiceApi;
import eqxiu.passport.sdk.dto.UserDTO;

/**
 * @description:订单
 * @Author: lifen
 * @Date: 2019/4/8 13:44
 */
@RestController
@RequestMapping("/api/m/order")
public class OrderApiController implements OrderApiDoc, BaseApiController {

    private static final int PAYWAY_WECHAT = 0;

    @Autowired
    private IOrderServiceApi orderServiceApi;

    @Autowired
    private IOrderItemServiceApi orderItemServiceApi;

    @Autowired
    private ProductServiceApi productServiceApi;

    @Autowired
    private AsyncOrderCallbackServiceApi callbackServiceApi;

    @Value("${payment.appid}")
    private String paymentAppId;

    @Value("${payment.notify}")
    private String paymentNotify;

    @Value("${payment.notifyCharge}")
    private String paymentNotifyCharge;

    @Value("${payment.notifyTailer}")
    private String paymentNotifyTailer;

    @Value("${payment.appkey}")
    private String appKey;

    @Autowired
    private IMallServiceApi mallServiceApi;
    @Autowired
    private UserApi userApi;

    private final Logger logger = LoggerFactory.getLogger(OrderApiController.class);

    @Autowired
    private ObjectMapper mapper;
    // 样例模板
    private final int SCENE_ATTR_GROUP_ID = 2;
    // 实时数据价格
    private final int SCENE_DATE_IN_TIME = 5;
    // 实时数据和推送组合价格
    private final int SCENE_DATE_IN_TIME_PUSH = 8;

    @PostMapping(value = "/create")
    @Override
    public ResultData createOrder(@RequestBody OrderDTO orderDTO, HttpServletRequest req) {
        Map<String, Object> map = new TreeMap<String, Object>();
        try {
        	String notifyUrl = orderDTO.getNotifyUrl();
            String code = orderDTO.getProductCode();
            Integer productId = orderDTO.getProductId();
            boolean existCode = !StringUtils.isEmpty(code);
            if (!existCode && productId == null || orderDTO.getPayType() == null) {
                return fail().setCode(MsgCode.CONSTRAINT_VIOLATION).setMsg("create order failed, code or id or payType is null");
            }
            Map<String, Object> prod = Maps.newHashMap();
            if (existCode) {
                prod = productServiceApi.getProductLiteByCodeAndAttrGroupId(code, SCENE_ATTR_GROUP_ID);
            } else {
                prod = productServiceApi.getProductLite(productId);
            }
            if (prod == null) {
                return fail().setCode(MsgCode.DATA_NOT_EXIST).setMsg("product not exist");
            }
            String title = prod.get("title").toString();
            //原价格
            int originalPrice = Integer.parseInt(prod.get("price").toString());
            int prodId = Integer.parseInt(prod.get("id").toString());
            code = prod.get("code").toString();
            UserDTO currentUser = UserContext.getUser();
            //获取价格
            int price = getPrice(currentUser,prod);

            orderDTO.setCreateUser(currentUser.getId());
            orderDTO.setProductId(prodId);
            orderDTO.setName(title);

            Integer orderType = orderDTO.getPayType();
            if (orderType == OrderTypeEnum.Charge.getState()) {
                // 充值订单
                Integer goodsId = 25;
                Integer amount = 1;
                map.put("goodsId", goodsId);
                map.put("amount", amount);
                map.put("price", originalPrice);
                // 如果有优惠券且价格>0
                if (Objects.nonNull(orderDTO.getCouponId()) && orderDTO.getTotalFee() > 0) {
                    map.put("price", orderDTO.getTotalFee());
                } else {
                    orderDTO.setTotalFee(originalPrice);
                }
                map.put("remark", orderDTO.getRemark());
                map.put("payway", PAYWAY_WECHAT);
				map.put("notifyUrl", notifyUrl == null ? paymentNotifyCharge : notifyUrl);
            } else if (orderType == OrderTypeEnum.COST.getState()) {
                // 消耗
                orderDTO.setTotalFee(price);
                map.put("orderAmount", price);
                Map<String, Object> props = new LinkedHashMap<>();
                props.put("productId", prodId);
                props.put("productName", title);
                props.put("code", code);
                map.put("orderRemark", orderDTO.getRemark());
                map.put("properties", mapper.writeValueAsString(props));
                map.put("orderType", "PAYXB");
                map.put("notifyUrl", notifyUrl == null ? paymentNotify : notifyUrl );
            }
            OrderDTO order = orderServiceApi.createOrder(orderDTO);
            if (order!=null){
                map.put("orderTradeId", order.getId());
                orderDTO.setId(order.getId());
            }
            map.put("orderAppId", paymentAppId);
            logger.info("sign param {}", map.toString());
            String sign = orderServiceApi.signParam(map, appKey);
            map.put("sign", sign);
        } catch (Exception e) {
            logger.error("createOrder", e);
        }
        return success().setObj(orderDTO).setMap(map);
    }


    public int getPrice(UserDTO currentUser,Map<String, Object> prod){

        int orderAmount=0;
        //原价
        Integer price = (Integer) prod.get("price");
        try {
            //////获取商品价格信息start
            //折扣标识
            boolean discountFlag = (Boolean) prod.get("discountFlag");
            //会员特价标识
            boolean memberDiscountFlag = false;
            if (prod.get("memberDiscountFlag") != null) {
                memberDiscountFlag = (Boolean) prod.get("memberDiscountFlag");
            }
            //折扣价
            Integer discountPrice = null;
            if (prod.get("discountPrice") != null) {
                discountPrice = (Integer) prod.get("discountPrice");
            }
            //会员特价
            Integer memberDiscoutPrice = null;
            if (prod.get("memberPrice") != null) {
                memberDiscoutPrice = (Integer) prod.get("memberPrice");
            }
            System.out.println("======折扣标识：" + discountFlag + "，会员特价标识" + memberDiscountFlag);
            System.out.println("======原价：" + price + "，折扣价：" + discountPrice + "，会员价" + memberDiscoutPrice);
            //获取商品价格信息end
            //判断用户类型
            User u = userApi.getUser(currentUser.getId());
            UserExt ext = userApi.getUserExt(currentUser.getId());
             //判断是否是企业账号or企业子账号
            if (ext != null && ext.getMemberType() != null && u.getType() == 2 || u.getType() == 21 || u.getType() == 22) {
                //判断付费版企业会员
                if (ext.getMemberType() != null && (ext.getMemberType().equals(7) || ext.getMemberType().equals(8) || ext.getMemberType().equals(9))|| verifyMember(u.getId())) {
                    //无折扣&无会员特价--原价
                    if (!discountFlag && !memberDiscountFlag) {
                        orderAmount = price;
                    }
                    //会员折扣
                    if (memberDiscountFlag) {
                        orderAmount = memberDiscoutPrice;
                    }
                    //打折
                    if (!memberDiscountFlag && discountFlag) {
                        orderAmount = discountPrice;
                    }
                } else {
                    //判断子账号的父账号是否是会员
                    String parentId = ext.getCompanyId();
                    if (org.apache.commons.lang3.StringUtils.isNotBlank(parentId)) {
                        UserExt parent = userApi.getUserExt(parentId);
                        if (parent != null && parent.getMemberType() != null && (parent.getMemberType().equals(7) || parent.getMemberType().equals(8) || parent.getMemberType().equals(9))) {
                            //无折扣&无会员特价--原价
                            if (!discountFlag && !memberDiscountFlag) {
                                orderAmount = price;
                            }
                            //会员折扣
                            if (memberDiscountFlag) {
                                orderAmount = memberDiscoutPrice;
                            }
                            //打折
                            if (!memberDiscountFlag && discountFlag) {
                                orderAmount = discountPrice;
                            }
                        }
                    } else {
                        //无折扣--原价
                        if (!discountFlag) {
                            orderAmount = price;
                        }
                        //打折
                        if (discountFlag) {
                            orderAmount = discountPrice;
                        }
                    }
                }
            } else if (verifyMember(currentUser.getId())) {
                //判断是否是创意云会员
                //无折扣&无会员特价--原价
                if (!discountFlag && !memberDiscountFlag) {
                    orderAmount = price;
                }
                //会员折扣
                if (memberDiscountFlag) {
                    orderAmount = memberDiscoutPrice ;
                }
                //打折
                if (!memberDiscountFlag && discountFlag) {
                    orderAmount = discountPrice ;
                }
                System.out.println("创意云会员：" + currentUser.getId() + "===支付价格：" + orderAmount);
            } else {
                //普通用户
                //无折扣--原价
                if (!discountFlag) {
                    orderAmount = price;
                }
                //打折
                if (discountFlag) {
                    orderAmount = discountPrice ;
                }
                System.out.println("普通账号/企业免费账号：" + currentUser.getId() + "===支付价格：" + orderAmount);
            }
        } catch (Exception e) {// 假异常
            e.printStackTrace();
            orderAmount = price;
        }
        return orderAmount;
    }

    /**
     * @return boolean
     * @Description 校验是否是创意云会员
     * @Author SuiXiangyu
     * @Date 2019/5/10
     * @Param [id]
     * update 增加超级会员判断
     **/
    private boolean verifyMember(String id) {
        boolean flag = false;
        //13，14-创意云会员，203、202、204是营销云会员，20-超级会员
        List<UserMemberDTO> userMemberList = userApi.getUserMemberList(id);
        if (userMemberList != null && userMemberList.size() > 0) {
            for (UserMemberDTO userMember : userMemberList) {
                if (userMember.getMemberId() != null && (userMember.getMemberId() == 13 ||
                        userMember.getMemberId() == 14||userMember.getMemberId() ==203 ||
                        userMember.getMemberId() ==204 ||userMember.getMemberId() ==202 || userMember.getMemberId() ==20)) {
                    flag = true;
                }
            }
        }
        return flag;
    }


    @PostMapping(value = "/create2")
    @Override
    public ResultData createOrder2(@RequestBody OrderDTO orderDTO, HttpServletRequest req) {
        Map<String, Object> map = new TreeMap<String, Object>();
        try {
            Integer totalFee = orderDTO.getTotalFee();
            if (totalFee <= 0) {
                return success().setCode(MsgCode.CONSTRAINT_VIOLATION).setMsg("total fee invalid");
            }
            UserDTO currentUser = UserContext.getUser();
            orderDTO.setCreateUser(currentUser.getId());
            List<ItemDTO> items = orderDTO.getItems();
            if (items != null) {
                // hard code totalFee
                if (items.size() == 1 && totalFee != SCENE_DATE_IN_TIME) {
                    return success().setCode(MsgCode.CONSTRAINT_VIOLATION).setMsg("total fee invalid");
                }
                if (items.size() == 2 && totalFee != SCENE_DATE_IN_TIME_PUSH) {
                    return success().setCode(MsgCode.CONSTRAINT_VIOLATION).setMsg("total fee invalid");
                }
                if (items.size() >= 3) {
                    return success().setCode(MsgCode.CONSTRAINT_VIOLATION).setMsg("items invalid");
                }
            }
            orderServiceApi.createOrder(orderDTO);

            map.put("orderAmount", orderDTO.getTotalFee());
            map.put("orderAppId", paymentAppId);
            map.put("orderTradeId", orderDTO.getId());
            Map<String, Object> props = new LinkedHashMap<>();
            props.put("productName", orderDTO.getName());
            if (orderDTO.getProductId() != null) {
                props.put("productId", orderDTO.getProductId());
            }
            if (orderDTO.getProductCode() != null) {
                props.put("code", orderDTO.getProductCode());
            }
            map.put("orderRemark", orderDTO.getRemark());
            map.put("properties", mapper.writeValueAsString(props));
            map.put("orderType", "PAYXB");
            map.put("notifyUrl", paymentNotifyTailer);
            logger.info("sign param {}", map.toString());
            String sign = orderServiceApi.signParam(map, appKey);
            map.put("sign", sign);
        } catch (Exception e) {
            logger.error("create2", e);
        }
        return success().setObj(orderDTO).setMap(map);
    }

    @GetMapping(value = "/{orderId}")
    @Override
    public ResultData queryOrder(@PathVariable("orderId") Long orderId) throws Exception {
        UserDTO currentUser = UserContext.getUser();
        OrderDTO condition = new OrderDTO();
        condition.setCreateUser(currentUser.getId());
        condition.setId(orderId);
        List<OrderDTO> orders = orderServiceApi.findByCondition(condition);
        if (orders.isEmpty()) {
            return fail().setCode(MsgCode.DATA_NOT_EXIST).setMsg("order not exist");
        }
        OrderDTO dto = orders.get(0);
        if (dto.getAsyncId() != null) {
            Map<String, Object> result = callbackServiceApi.isOrderCallbackSuccessById(dto.getAsyncId());
            return success().setObj(dto).setMap(result);
        }
        return success().setObj(dto);
    }

    @RequestMapping(value = "/try-use", method = {RequestMethod.GET, RequestMethod.POST})
    @Override
    public ResultData useProduct(@RequestParam(required = true) String code, @RequestParam(required = false, defaultValue = "4") Integer source) {
        UserDTO currentUser = UserContext.getUser();
        OrderDTO condition = new OrderDTO();
        condition.setCreateUser(currentUser.getId());
        condition.setStatus(OrderStatusEnum.PAID.status());
        condition.setPayType(OrderTypeEnum.COST.getState());
        condition.setCode(code);
        List<OrderDTO> orders = orderServiceApi.findByCondition(condition);
        if (orders.isEmpty()) {
            logger.error("try use product failed , order not exist. code={},userid={}", code, currentUser.getId());
            return fail().setCode(MsgCode.DATA_NOT_EXIST).setMsg("order not exist");
        }
        OrderDTO dto = orders.get(0);
        String channel = dto.getChannel();
        //做兼容
        source = determineCallbackSource(channel, source);
        Map<String, Object> result = mallServiceApi.createCallback("PAYXB", dto.getTotalFee() + "", dto.getProductId(), currentUser.getId(), dto.getMallOrderId(), true, source);
        if (result == null) {
            logger.error("create mall callback failed product id {}, userid {}, mall order id : {}", dto.getProductId(), currentUser.getId(), dto.getMallOrderId());
        }

        Integer asyncId = (Integer) result.get("id");
        dto.setAsyncId(asyncId);
        orderServiceApi.finishOrder(dto);
        return success().setObj(dto);
    }

    @RequestMapping(value = "/exist", method = {RequestMethod.GET, RequestMethod.POST})
    @Override
    public ResultData hasOrder(@RequestParam String code, @RequestParam Integer itemType) {
        UserDTO currentUser = UserContext.getUser();
        return success().setObj(orderItemServiceApi.countByItemType(currentUser.getId(), code, itemType) > 0);
    }

    public static Integer determineCallbackSource(final String channel, Integer source) {
        if ("wphk".equals(channel)) {
            //wap 端贺卡
            source = Constants.WAP_CARD_SOURCE;
        } else if ("wpapp".equals(channel)) {
            //wap商城
            source = Constants.WAP_SOURCE;
        }
        return source;
    }

}
